package org.luxor.common.netty.protocol.handler.connect;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import org.luxor.common.netty.config.option.GrantOption;
import org.luxor.common.netty.config.properties.NettyServerProperties;
import org.luxor.common.netty.constant.NettyReasonCode;
import org.luxor.common.netty.protocol.NettyConnectVariableHeader;
import org.luxor.common.netty.protocol.NettyFixedHeader;
import org.luxor.common.netty.protocol.message.NettyConnAckMessage;
import org.luxor.common.netty.protocol.message.NettyConnectMessage;
import org.luxor.common.netty.protocol.message.NettyDisconnectMessage;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * 建立连接
 *
 * @author Mr.yan @date 2023/12/8
 */
public class ConnectMessageHandler extends SimpleChannelInboundHandler<NettyConnectMessage> {

    /**
     * 客户端标识
     */
    public static final AttributeKey<String> CLIENT_IDENTIFIER_ATTRIBUTE_KEY = AttributeKey.valueOf("clientIdentifier");

    private final NettyServerProperties serverProperties;

    public ConnectMessageHandler(NettyServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, NettyConnectMessage connectMessage) throws Exception {
        /*---------------------------解析接收的消息----------------------------*/
        NettyFixedHeader fixedHeader = connectMessage.fixedHeader();
        NettyConnectVariableHeader variableHeader = connectMessage.variableHeader();

        /*------------------------------处理消息------------------------------*/
        // 配置通道所属ClientId标识
        String clientId = variableHeader.clientId();
        ctx.channel().attr(ConnectMessageHandler.CLIENT_IDENTIFIER_ATTRIBUTE_KEY).set(clientId);

        // 如果,不需要认证授权账号,直接发送应答消息(认证成功)
        if (CollectionUtils.isEmpty(serverProperties.getGrants())) {
            ctx.channel().writeAndFlush(NettyConnAckMessage.from(NettyReasonCode.SUCCESS));
            return;
        }

        // 检查参数合法性
        String username = variableHeader.username();
        String password = variableHeader.password();
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            // 发送应答消息(用户名或密码为空)
            authenticationFailure(ctx, NettyReasonCode.CONNECTION_CLIENT_ID_NOT_VALID);
            return;
        }

        // 检查账号密码合法性
        for (GrantOption o : serverProperties.getGrants()) {
            if (o.getClientId().equals(clientId) && username.equals(o.getUsername())) {
                if (!password.equals(o.getPassword())) {
                    // 发送应答消息(密码错误)
                    authenticationFailure(ctx, NettyReasonCode.CONNECTION_CLIENT_ID_NOT_VALID);
                    return;
                }
                // 添加客户端缓存
                //serverProperties.sessionManager().save(clientId, ctx.channel());
                // 发送应答消息(认证合法)
                ctx.channel().writeAndFlush(NettyConnAckMessage.from(NettyReasonCode.SUCCESS));
                return;
            }
        }

        // 发送应答消息(客户端标识符无效)
        authenticationFailure(ctx, NettyReasonCode.CONNECTION_CLIENT_ID_NOT_VALID);
    }

    private void authenticationFailure(ChannelHandlerContext ctx, NettyReasonCode reasonCode) {
        ctx.channel().writeAndFlush(NettyConnAckMessage.from(reasonCode));
        ctx.channel().writeAndFlush(NettyDisconnectMessage.from(NettyReasonCode.DISCONNECT));
        ctx.fireChannelInactive();
        ctx.close();
    }
}
